/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package taquin_console;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import sun.net.www.content.image.gif;

/**
 *
 * @author Caroline
 */
public final class Taquin {

    private int taille;
    private Grille ei;
    private Grille ec;
    private Grille ef;
    private LinkedList<Grille> l;
    private LinkedList<Grille> lv;
    private Heuristique h;

    public static void main(String args[]) {
        Taquin t = new Taquin(3,Heuristique.W);
        if (t.taille == 3) {
//            t.setH(Heuristique.P3S);
//            t.generateChildren();
        }

     //   t.setH(Heuristique.P);
        
        t.generateChildren();
    }

    public Taquin(int taille) {
        this.taille = taille;
        etatFinal();
        generateEtatInitial();
        this.l = new LinkedList<>();
        this.lv = new LinkedList<>();
        l.add(this.ec);

    }
    
    public Taquin(int taille, Heuristique h) {
        this.taille = taille;
        this.h=h;
        etatFinal();
        generateEtatInitial();
        this.l = new LinkedList<>();
        l.add(this.ec);
        
        

    }

    private void generateEtatInitial() {
        int t = taille * taille;
        ArrayList<Integer> a = new ArrayList<>();
        int i, k = 0;
        for (i = 0; i < t; i++) {
            a.add(i);
        }
        Collections.shuffle(a);
        ei = new Grille(taille);
        ei.setPoids(0);
        ei.setNiveau(0);
        int[][] c = new int[taille][taille];
        for (i = 0; i < taille; i++) {
            for (int j = 0; j < taille; j++) {
                if (a.get(k) == 0) {
                    ei.setPositionVide(i, j);
                }
                c[i][j] = a.get(k);
                k++;
            }
        }

        ei.setCases(c);
        ec = ei;
        ec.setHeuristique(h, ef);

    }

    public void etatFinal() {
        ef = new Grille(taille);
        int k = 0;
        for (int i = 0; i < this.taille; i++) {
            for (int j = 0; j < this.taille; j++) {
                ef.setCase(i, j, k);

                k++;
            }
        }

    }

    private void echangerCases() throws CloneNotSupportedException {
        Grille g=null;
        g = ec.deplacerVideHaut();
        if (g != null) {
            insererGrille(g);
        }
        g = ec.deplacerVideBas();

        if (g != null) {
            insererGrille(g);
        }
        g = ec.deplacerVideGauche();
        if (g != null) {
            insererGrille(g);
        }
        g = ec.deplacerVideDroite();
        if (g != null) {
            insererGrille(g);
        }

    }

    private void insererGrille(Grille g) {
         //ajout poid heurisitque
        boolean visited = false;
        for (Grille gv : lv) {
            if (Arrays.deepEquals(g.getCases(), gv.getCases())) {
                visited = true;
                break;
            } 
        }
        if (!visited) {
            int pg, pgrilleliste;
            boolean addGrille = false;
            g.setHeuristique(h, ef);
            for (Grille grilleliste : l) {
                pgrilleliste = grilleliste.getPoids() + grilleliste.getNiveau();
                //pgrilleliste = grilleliste.getPoids();
                pg = g.getPoids() + g.getNiveau();
                //pg = g.getPoids();
                if (pgrilleliste > pg) {
                    l.add(l.indexOf(grilleliste), g);
                    addGrille = true;
                    break;
                }
            }
            if (!addGrille) {
                l.addLast(g);
            }
            lv.add(g);
        }

    }

    private void generateChildren() {
        int i=0;
       while(ec.getPoids()!=0) {
           
            ec = l.getFirst();
            try {
                echangerCases();
            } catch (CloneNotSupportedException ex) {
                Logger.getLogger(Taquin.class.getName()).log(Level.SEVERE, null, ex);
            }
            l.remove(ec);
            
            System.out.print(l.getFirst());
            i++;
        System.out.print("\n"+i+"---"+ltostring(l)+"\n");
        }
        System.out.print("bien ouej");

    }

    public Heuristique getH() {
        return h;
    }

    public void setH(Heuristique h) {
        this.h = h;
    }

    public Grille getEc() {
        return ec;
    }

    public void setEc(Grille ec) {
        this.ec = ec;
    }

    public Grille getEf() {
        return ef;
    }

    public Grille getEi() {
        return ei;
    }

    public void setEi(Grille ei) {
        this.ei = ei;
    }

    public LinkedList<Grille> getL() {
        return l;
    }

    public void setL(LinkedList<Grille> l) {
        this.l = l;
    }

    public int getTaille() {
        return taille;
    }

    public void setTaille(int taille) {
        this.taille = taille;
    }
    
    public String ltostring(LinkedList<Grille> l){
       int p;
       String s="";
        for (Grille grille : l) {
            p=grille.getPoids();
            s+="Poids: "+p+"\n";
        }
        return s;
    }
}
